#include <memory>
#include <sys/epoll.h>
#include <wait.h>
#include <functional>
#include <sys/select.h>
#include "Common.hpp"
#include "Socket.hpp"
#define FDSIZE 1024
#define MAXEVENTS 128
int const fd_default = -1;
using namespace SocketMoudule;
using ioservice_t = function<void(shared_ptr<Socket> &, InetAddr &)>;
class TcpServer
{
public:
    TcpServer(uint16_t port)
        : _port(port), _listensockptr(make_unique<TcpSocket>(port)), _isrunning(false)
    {
        _listensockptr->BuildTcpServerMoudule(_port);
        _epfd = epoll_create1(0);
        if (_epfd < 0)
        {
            LOG(Level::FATAL) << "epoll_create fail";
            exit(EPOLL_CREATE_ERRO);
        }
        else
            LOG(Level::INFO) << "epoll_create success";
        epoll_event event;
        event.data.fd = _listensockptr->Fd();
        event.events = EPOLLIN;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensockptr->Fd(), &event);
        if (n < 0)
        {
            LOG(Level::FATAL) << "listen epoll_ctl fail";
            exit(EPOLL_CTL_ERRO);
        }
        else
            LOG(Level::INFO) << "listen epoll_ctl success";
    }
    //处理普通fd获取
    void SolveAccept()
    {
        InetAddr client;
        auto sock = _listensockptr->Accept(&client);
        epoll_event event;
        event.data.fd = sock->Fd();
        event.events = EPOLLIN;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sock->Fd(), &event);
        if (n < 0)
            LOG(Level::WARING) << "accept epoll_ctl fail";
        else
            LOG(Level::INFO) << "accept epoll_ctl success";
    }
    //处理读数据
    void SolveRead(int fd)
    {
        char buffer[1024];
        int n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (n == 0)
        {
            epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            close(fd);
            cout << "client " << fd << " out..." << endl;
        }
        else if (n < 0)
        {
            epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            close(fd);
            cout << "client " << fd << "recv fail" << endl;
        }
        else
        {
            buffer[n] = '\0';
            cout << "client say@: " << buffer << endl;
        }
    }
    void Start(ioservice_t callout)
    {
        _isrunning = true;
        while (_isrunning)
        {
            int tm = 1000;
            int n = epoll_wait(_epfd, _events, MAXEVENTS, tm);
            //函数执行错误
            if (n < 0)
            {
                LOG(Level::WARING) << "epoll_wait fail\n";
            }
            // 超时
            else if (n == 0)
            {
                cout << "overtime..." << endl;
            }
            // 事件派发
            else
            {
                for (int i = 0; i < n; i++)
                {
                    if (_events[i].events | EPOLLIN)
                    {
                        if (_events[i].data.fd == _listensockptr->Fd())
                            SolveAccept();
                        else
                            SolveRead(_events[i].data.fd);
                    }
                }
            }
        }
    }

private:
    uint16_t _port;
    unique_ptr<Socket> _listensockptr;
    bool _isrunning;
    int _epfd;
    struct epoll_event _events[MAXEVENTS];
};